// 计算器主程序
// 作者: Hollson
// 日期: 2025/2/11
// AArch64汇编计算器完整实现 

.global _start 
.align 4 
 
// 数据段定义 
.section .data 
prompt: .asciz "请输入表达式 (例如 23+15): \n"
input_err: .asciz "输入格式错误！\n"
divzero_err: .asciz "除零错误！\n"
buffer: .space 64 
result_str: .asciz "计算结果: "
newline: .asciz "\n"
 
// 代码段定义 
.section .text 
 
_start:
    // 打印提示信息 
    ldr x0, =prompt 
    bl print_string 
 
    // 读取用户输入 
    ldr x0, =buffer 
    mov x1, #64 
    bl read_input 
 
    // 解析表达式 
    ldr x0, =buffer 
    bl parse_expression 
    cmp x0, #-1 
    beq input_error 
    cmp x0, #-2 
    beq div_zero 
 
    // 保存计算结果 
    mov x19, x0 
 
    // 打印结果前缀 
    ldr x0, =result_str 
    bl print_string 
 
    // 打印实际数值 
    mov x0, x19 
    bl print_number 
 
    // 换行 
    ldr x0, =newline 
    bl print_string 
 
    // 正常退出 
    mov x8, #93 
    svc #0 
 
input_error:
    ldr x0, =input_err 
    bl print_string 
    mov x8, #93 
    svc #0 
 
div_zero:
    ldr x0, =divzero_err 
    bl print_string 
    mov x8, #93 
    svc #0 
 
// 打印字符串子程序 
// x0 = 字符串地址 
print_string:
    stp x29, x30, [sp, -16]!
    mov x1, x0 
    bl strlen 
    mov x2, x0 
    mov x0, #1 
    mov x8, #64 
    svc #0 
    ldp x29, x30, [sp], 16 
    ret 
 
// 计算字符串长度 
// x0 = 字符串地址，返回长度x0 
strlen:
    mov x1, #0 
1:  ldrb w2, [x0, x1]
    cbz w2, 2f 
    add x1, x1, #1 
    b 1b 
2:  mov x0, x1 
    ret 
 
// 读取输入子程序 
// x0 = 缓冲区地址，x1 = 最大长度 
read_input:
    stp x29, x30, [sp, -16]!
    mov x2, x1 
    mov x1, x0 
    mov x0, #0 
    mov x8, #63 
    svc #0 
    ldp x29, x30, [sp], 16 
    ret 
 
// 表达式解析子程序 
// x0 = 输入缓冲区地址，返回结果x0，错误返回-1 
parse_expression:
    stp x29, x30, [sp, -32]!
    mov x19, x0 
    mov x20, #0  // 第一个操作数 
    mov x21, #0  // 第二个操作数 
    mov x22, #0  // 运算符 
    mov x23, #0  // 当前数值 
 
    // 解析第一个数字 
1:  ldrb w24, [x19], #1 
    cmp w24, #'0'
    blt 2f 
    cmp w24, #'9'
    bgt 2f 
    sub w25, w24, #'0'
    mov x26, #10 
    madd x23, x23, x26, x25 
    b 1b 
 
2:  // 保存第一个操作数 
    mov x20, x23 
    mov x23, #0 
 
    // 保存运算符 
    mov x22, x24 
 
    // 解析第二个数字 
3:  ldrb w24, [x19], #1 
    cmp w24, #0 
    beq 4f 
    cmp w24, #'0'
    blt 4f 
    cmp w24, #'9'
    bgt 4f 
    sub w25, w24, #'0'
    madd x23, x23, x10, x25 
    b 3b 
 
4:  // 保存第二个操作数 
    mov x21, x23 
 
    // 执行运算 
    cmp x22, #'+'
    beq add 
    cmp x22, #'-'
    beq sub 
    cmp x22, #'*'
    beq mul 
    cmp x22, #'/'
    beq div 
 
    // 无效运算符 
    mov x0, #-1 
    b 5f 
 
add:
    add x0, x20, x21 
    b 5f 
sub:
    sub x0, x20, x21 
    b 5f 
mul:
    mul x0, x20, x21 
    b 5f 
div:
    cbz x21, div_err 
    udiv x0, x20, x21 
    b 5f 
div_err:
    mov x0, #-2 
 
5:  ldp x29, x30, [sp], 32 
    ret 
 
// 数字打印子程序 
// x0 = 要打印的数字 
print_number:
    stp x29, x30, [sp, -48]!
    mov x19, x0 
    mov x20, sp 
    mov x21, #0 
 
    // 处理0的特殊情况 
    cbz x19, zero_case 
 
    // 分解各位数字 
1:  mov x0, x19 
    mov x1, #10 
    udiv x19, x0, x1 
    msub x22, x19, x1, x0 
    add x22, x22, #'0'
    strb w22, [x20, x21]
    add x21, x21, #1 
    cbnz x19, 1b 
 
    // 逆序输出 
2:  sub x21, x21, #1 
    ldrb w0, [x20, x21]
    mov x1, #1 
    mov x8, #64 
    mov x2, #1 
    svc #0 
    cbnz x21, 2b 
    b exit_print 
 
zero_case:
    mov w0, #'0'
    mov x1, #1 
    mov x8, #64 
    mov x2, #1 
    svc #0 
 
exit_print:
    ldp x29, x30, [sp], 48 
    ret 
 